package scantask.server.domainLayer;

import java.util.Vector;

import scantask.server.dataLayer.DataManipulatorInterface;
import scantask.server.dataLayer.exceptions.GetAreaException;
import scantask.server.dataLayer.exceptions.GetPasswordException;
import scantask.server.dataLayer.exceptions.GetUserException;
import scantask.server.domainLayer.Exceptions.LoginException;

import scantask.containers.Area;
import scantask.containers.User;
import scantask.containers.exceptions.UnInitializeObjectException;

public class UserController {
	
	private DataManipulatorInterface _dataManipulator;
	
	private Vector<User> _users;
	
	public UserController(DataManipulatorInterface dataManipulator) {
		
		this._dataManipulator = dataManipulator;
		
		this._users = new Vector<User>();
		
	}
	
	
	/**
	 *	check if the user userName exist in the system and it's stored password
	 *	is password then add him to the login users vector
	 * @param userName - userName
	 * @param password - password
	 * @throws LoginException 
	 * @throws GetPasswordException
	 * @throws GetUserException
	 */
	public User login(String userName, String password) throws LoginException {
		String storedPassword = "";
		try {
			// get the user password
			storedPassword = this._dataManipulator.getPassword(userName);
		} catch (GetPasswordException e) {
			scantask.server.utilities.logging.SingletonLogger.getLogger().warning("login is failed");
			throw new LoginException(e.getErrorDescription());
		}
		// compared the stored password with given password
		if (password.compareTo(storedPassword) == 0) {
			// check that the users vector does not contain this user yet
			synchronized (this._users) {
				for (int i = 0; i < this._users.size(); i++) {
					// if the user try to login where he already logged in
					if (this._users.get(i).getUserName().compareTo(userName) == 0) {
						return this._users.get(i);
					}
				}
				try {
					// add the user to the login users vector
					User ans = this._dataManipulator.getUser(userName);
					ans.setUserAreas(this.getUserAreaFromDataBase(userName));
					this._users.add(ans);
					return ans;
					
				} catch (GetUserException e) {
					scantask.server.utilities.logging.SingletonLogger.getLogger().warning("login is failed");
					throw new LoginException(e.getErrorDescription());
				} catch (GetAreaException e) {
					scantask.server.utilities.logging.SingletonLogger.getLogger().warning("login is failed");
					throw new LoginException(e.getErrorDescription());
				}
			}
		}
		else {
			scantask.server.utilities.logging.SingletonLogger.getLogger().warning("login is failed, wrong password");
			throw new LoginException("Login is failed, wrong password");
		}
		
	}

	/**
	 * remove user userName from login users vector
	 * @param userName - userName
	 */
	public void logout(String userName) {
		synchronized (this._users) {
			int index = -1;
			// find the user index in login users vector
			for (int i = 0; i < this._users.size(); i++) {
				if (this._users.get(i).getUserName().compareTo(userName) == 0) {
					index = i;
					break;
				}
			}
			// remove the user from login users vector
			if (index >= 0) {
				this._users.remove(index);
			}
		}
	}
	
	/**
	 * check if the user userName is logged in
	 * @param userName - userName
	 * @return true if userName exist in users vector
	 */
	public boolean isLoggedIn(String userName) {
		
		synchronized (this._users) {
			for (int i = 0; i < this._users.size(); i++) {
				if (this._users.get(i).getUserName().compareTo(userName) == 0) {
					return true;
				}
			}
		}
		return false;
	}
	
	private Vector<Area> getUserAreaFromDataBase(String userName) throws GetAreaException {
		return this._dataManipulator.getArea(userName);
	}
	
	public Vector<Area> getUserAreas(String userName) throws UnInitializeObjectException, LoginException {
		synchronized (this._users) {
			for (int i = 0; i < this._users.size(); i++) {
				if (this._users.get(i).getUserName().compareTo(userName) == 0) {
					return this._users.get(i).getUserAreas();
				}
			}
		}
		throw new LoginException("The user shall logged in, in order to get user areas");
	}

/* already get it in the login	
	/**
	 * 
	 * @param userName - userName
	 * @return user full name if exist in the system, 
	 * otherwise return the empty string
	 */ /*
	public String getUserFullName(String userName) {
		synchronized (this._users) {
			for (int i = 0; i < this._users.size(); i++) {
				if (this._users.get(i).getUserName().compareTo(userName) == 0) {
					return this._users.get(i).getFullName();
				}
			}
		}
		return "";
	}
	*/

}
